//
// Created by LiuYou on 2021/12/8.
//

#include <iostream>
#include <memory>
#include <utility>


class Cat {
public:
    Cat(const std::string& name, int age) : pImpl( std::make_unique<Impl>( name, age )) {}

private:
    class Impl;

    std::unique_ptr<Impl> pImpl;
public:
    friend std::ostream& operator<<(std::ostream& os, const Cat& cat);
};


/* ***************************************************** */


class Cat::Impl {
public:
    std::string name;
    int age;

    Impl(std::string name, int age) : name( std::move( name )), age( age ) {}

public:
    /*
     * todo 笔记: 注意: !!!!!!!!!!!!!!!!!!!
     *  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     *  因为 Impl 是 private: 的, 所以, 这个流操作运算符重载函数不要写在类的外面, 一定要写在类的里面,
     *  不然就是错误的！！！！！！！
     */
    friend std::ostream& operator<<(std::ostream& os, const Impl& rhs) {
        os << "name: " << rhs.name << " age: " << rhs.age;
        return os;
    }
};


/*
 * todo 笔记: 而这个 stream output operator 写在类内部和外部都是可以的。
 */
inline std::ostream& operator<<(std::ostream& os, const Cat& cat) {
//    os << "pImpl: " << *cat.pImpl;
//    os << typeid( Cat ).name() << " " << *cat.pImpl;
    os << typeid( Cat ).name() << "{" << *cat.pImpl << "}";
    return os;
}


int main(int argc, char** argv) {
    Cat myCat( "喵喵", 2 );
    std::cout << myCat << std::endl;


    return 0;
}
